home *** CD-ROM | disk | FTP | other *** search
/ Aminet 33 / Aminet 33 - October 1999.iso / Aminet / util / misc / VMM_src.lha / VMM / mem_tracking.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-16  |  8.1 KB  |  338 lines

  1. #include <exec/types.h>
  2. #include "defs.h"
  3.  
  4. static char rcsid [] = "$Id: mem_tracking.c,v 3.7 95/12/16 18:37:03 Martin_Apel Exp $";
  5.  
  6. /**********************************************************************/
  7.  
  8. /* The following structure is exported to the public. It should never 
  9.  * change. If it ever does, it has to be changed in include/VMM_Stat.h 
  10.  * too.
  11.  */
  12.  
  13. struct TaskVMUsage
  14.   {
  15.   struct Node vu_Node;
  16.   ULONG  VMInUse;
  17.   ULONG  StructSize;
  18.   };
  19.  
  20. /**********************************************************************/
  21. /* These are private */
  22.  
  23. struct TaskNameInfo
  24.   {
  25.   struct MinNode TN_Node;
  26.   UWORD Size;                 /* of this struct plus taskname buffer  */
  27.   char *Name;                 /* Note: this is the same offset as in  */
  28.                               /* a struct Node. This way FindName can */
  29.                               /* be used.                             */
  30.   ULONG UsageCnt;             /* How often is this task name used,    */
  31.   };                          /* if == 0, remove this entry           */
  32.  
  33. struct TrackInfo
  34.   {
  35.   struct MinNode MT_Node;
  36.   ULONG  Size;           /* Size of this allocation */
  37.   struct TaskNameInfo *TaskName;
  38.   };
  39.  
  40. PRIVATE struct List TaskNameList;
  41. PRIVATE struct List TrackAllocList;
  42. PRIVATE void *TrackPool;
  43.  
  44. /* Used for a temporary buffer for the task name. This could be allocated
  45.  * locally to CreateTrackInfo, but that may result in problems with
  46.  * tasks running low on stack. As CreateTrackInfo is only called within
  47.  * MEM_FORBID, it need not be reentrant.
  48.  * name_start is simply a pointer to the name_buffer if it's called from
  49.  * a normal task or the pointer to the last component of the path if it's
  50.  * called from a CLI
  51.  */
  52.  
  53. PRIVATE char name_buffer [100];
  54. PRIVATE char *name_start;
  55.  
  56. /**********************************************************************/
  57.  
  58. /* CreateTrackInfo and FreeTrackInfo must only be called from inside
  59.  * MEM_FORBID and MEM_PERMIT. They are protected by the same semaphore
  60.  * that protects virtual memory.
  61.  */
  62.  
  63. /**********************************************************************/
  64.  
  65. PRIVATE struct Node *FindIName (struct List *list, char *name)
  66.  
  67. {
  68. struct Node *tmp;
  69.  
  70. /* Does the same as FindName, but case-insensitive. */
  71. for (tmp = list->lh_Head; tmp->ln_Succ != NULL; tmp = tmp->ln_Succ)
  72.   {
  73.   if (Stricmp (tmp->ln_Name, name) == 0)
  74.     return (tmp);
  75.   }
  76.  
  77. return (NULL);
  78. }
  79.  
  80. /**********************************************************************/
  81.  
  82. PRIVATE struct TaskNameInfo *EnterTaskName (void)
  83.  
  84. {
  85. /* Enters the task name starting at 'name_start' into the name list.
  86.  * If it was already there, only its usage count is increased,
  87.  * otherwise a new node is created.
  88.  */
  89.  
  90. struct TaskNameInfo *tmp;
  91. ULONG size;
  92.  
  93. if ((tmp = (struct TaskNameInfo*) FindIName (&TaskNameList, name_start)) != NULL)
  94.   {
  95.   tmp->UsageCnt++;
  96.   return (tmp);
  97.   }
  98.  
  99. /* Create a new entry */
  100. size = sizeof (struct TaskNameInfo) + strlen (name_start) + 1L;
  101. if ((tmp = LibAllocPooled (TrackPool, size)) == NULL)
  102.   return (NULL);
  103.  
  104. tmp->Size = size;
  105. strcpy ((char*)(tmp + 1), name_start);
  106. tmp->Name = (char*)(tmp + 1);
  107. tmp->UsageCnt = 1;
  108. AddHead (&TaskNameList, (struct Node*)tmp);
  109. return (tmp);
  110. }
  111.  
  112. /**********************************************************************/
  113.  
  114. ULONG *CreateTrackInfo (ULONG *buffer, ULONG orig_size)
  115.  
  116. {
  117. /* Creates a header for the current allocation and returns the
  118.  * start of the buffer as it should be returned to the requesting task.
  119.  */
  120.  
  121. struct Task *AskingTask = FindTask (NULL);
  122. struct Process *AskingProcess;
  123. BOOL IsCLI = FALSE;
  124. char *name;
  125. struct TaskNameInfo *tni;
  126. struct TrackInfo *ti;
  127.  
  128. AskingProcess = (struct Process*)AskingTask;
  129.  
  130. if ((AskingTask->tc_Node.ln_Type == NT_PROCESS) && 
  131.     (AskingProcess->pr_CLI != NULL))
  132.   {
  133.   struct CommandLineInterface *CLI;
  134.  
  135.   CLI = (struct CommandLineInterface*) BADDR(AskingProcess->pr_CLI);
  136.   if (CLI->cli_CommandName != NULL)
  137.     {
  138.     name = (char*) BADDR (CLI->cli_CommandName);
  139.  
  140.     if (*(name + 1) != 0)
  141.       {
  142.       IsCLI = TRUE;
  143.       strncpy (name_buffer, name + 1, *name);
  144.       name_buffer [*name] = 0;
  145.       name_start = FilePart (name_buffer);
  146.       }
  147.     }
  148.   }
  149.  
  150. if (!IsCLI)
  151.   name_start = AskingTask->tc_Node.ln_Name;
  152.  
  153. tni = EnterTaskName ();
  154. if ((ti = LibAllocPooled (TrackPool, sizeof (struct TrackInfo))) == NULL)
  155.   {
  156.   /* Don't track this allocation */
  157.   return (buffer);
  158.   }
  159.  
  160. ti->Size = (orig_size + 7) & ~0x7;
  161. ti->TaskName = tni;
  162. AddHead (&TrackAllocList, (struct Node*)ti);
  163.  
  164. *buffer++ = (ULONG) ti;
  165. *buffer++ = TRACK_MAGIC;
  166. return (buffer);
  167. }
  168.  
  169. /**********************************************************************/
  170.  
  171. void FreeTrackInfo (void *TrackBuffer)
  172.  
  173. {
  174. struct TrackInfo *ti = (struct TrackInfo*) TrackBuffer;
  175. struct TaskNameInfo *tni;
  176.  
  177. if (ti == NULL)
  178.   return;
  179.  
  180. tni = ti->TaskName;
  181.  
  182. Remove ((struct Node*) ti);
  183. LibFreePooled (TrackPool, ti, sizeof (struct TrackInfo));
  184.  
  185. if (tni == NULL)
  186.   return;
  187.  
  188. if (--tni->UsageCnt != 0)
  189.   return;
  190.  
  191. Remove ((struct Node*)tni);
  192. LibFreePooled (TrackPool, tni, (ULONG)tni->Size);
  193. }
  194.  
  195. /**********************************************************************/
  196.  
  197. void ChangeOwner (ULONG *buffer)
  198.  
  199. {
  200. struct TrackInfo *ti = (struct TrackInfo*) *(buffer - 2);
  201. struct TaskNameInfo *tni;
  202. struct LoadingTaskStruct *cur;
  203. char *new_name;
  204.  
  205. PRINT_DEB ("ChangeOwner called", 0L);
  206.  
  207. if ((*(buffer - 1) != TRACK_MAGIC) || ti == NULL)
  208.   return;
  209.  
  210. if ((tni = ti->TaskName) == NULL)
  211.   return;
  212.  
  213. Forbid ();
  214. for (cur = (struct LoadingTaskStruct*)LoadingTasksList.lh_Head; 
  215.      cur->lt_Node.mln_Succ != NULL && cur->LoadingTask != SysBase->ThisTask;
  216.      cur = (struct LoadingTaskStruct*)cur->lt_Node.mln_Succ);
  217. Permit ();
  218.  
  219. if (cur->LoadingTask != SysBase->ThisTask)
  220.   return;
  221.  
  222. new_name = FilePart (cur->LoadfileName);
  223.  
  224. if (strcmp (tni->Name, new_name) == 0)
  225.   {
  226.   PRINT_DEB ("Old owner is new owner", 0L);
  227.   return;
  228.   }
  229.  
  230. PRINT_DEB ("Old owner was", 0L);
  231. PRINT_DEB (tni->Name, 0L);
  232. PRINT_DEB ("New owner is", 0L);
  233. PRINT_DEB (new_name, 0L);
  234.  
  235. OBTAIN_VM_SEMA;
  236. name_start = new_name;
  237.  
  238. if (--tni->UsageCnt == 0)
  239.   {
  240.   PRINT_DEB ("Removing old TaskNameInfo", 0L);
  241.   Remove ((struct Node*) tni);
  242.   LibFreePooled (TrackPool, tni, (ULONG) tni->Size);
  243.   }
  244.  
  245. tni = EnterTaskName ();
  246. ti->TaskName = tni;
  247. RELEASE_VM_SEMA;
  248. }
  249.  
  250. /**********************************************************************/
  251.  
  252. PRIVATE void EnterUsage (struct List *TaskList, char *name, ULONG amount)
  253.  
  254. {
  255. struct TaskVMUsage *tmp;
  256. ULONG free_size;
  257. char *file_part;
  258.  
  259. if ((tmp = (struct TaskVMUsage*)FindIName (TaskList, name)) != NULL)
  260.   {
  261.   /* Task is already in list. Add VMUsage */
  262.   tmp->VMInUse += amount;
  263.   }
  264. else
  265.   {
  266.   free_size = sizeof (struct TaskVMUsage) + (ULONG)strlen (name) + 1;
  267.   if ((tmp = DoOrigAllocMem (free_size, MEMF_PUBLIC)) != NULL)
  268.     {
  269.     tmp->VMInUse = amount;
  270.     strcpy ((char*)(tmp + 1), name);
  271.     tmp->vu_Node.ln_Name = (char*)(tmp + 1);
  272.     tmp->StructSize = free_size;
  273.     AddHead (TaskList, (struct Node*)tmp);
  274.     }
  275.   }
  276. }
  277.  
  278. /*****************************************************************/
  279.  
  280. void VMUsageInfo (struct VMMsg *UsageMsg)
  281.  
  282. {
  283. /* This function creates a list of tasks currently using virtual memory.
  284.  * The list entries are of type 'struct TaskVMUsage'. After the requesting  
  285.  * task has used the information it must free every single node and
  286.  * the list structure.
  287.  */
  288. struct TrackInfo *ti;
  289. struct List **TaskList;
  290.  
  291. PRINT_DEB ("CreateUsageInfo called", 0L);
  292.  
  293. TaskList = &(UsageMsg->UsageList);
  294.  
  295. if ((*TaskList = DoOrigAllocMem (sizeof (struct List), MEMF_PUBLIC)) == NULL)
  296.   return;
  297.  
  298. NewList (*TaskList);
  299.  
  300. OBTAIN_VM_SEMA;
  301.  
  302. for (ti = (struct TrackInfo*) TrackAllocList.lh_Head; 
  303.      ti->MT_Node.mln_Succ != NULL; 
  304.      ti = (struct TrackInfo*) ti->MT_Node.mln_Succ)
  305.   {
  306.   EnterUsage (*TaskList, ti->TaskName->Name, ti->Size);
  307.   }
  308.  
  309. RELEASE_VM_SEMA;
  310.  
  311. /* Reply to requesting task */
  312. PRINT_DEB ("Replying to requesting task", 0L);
  313. Signal (UsageMsg->VMSender, 1L << UsageMsg->ReplySignal);
  314. }
  315.  
  316. /*****************************************************************/
  317.  
  318. int InitTrackInfo (void)
  319.  
  320. {
  321. NewList (&TaskNameList);
  322. NewList (&TrackAllocList);
  323.  
  324. if ((TrackPool = LibCreatePool (MEMF_PUBLIC, 10000L, 1000L)) == NULL)
  325.   return (ERR_NOT_ENOUGH_MEM);
  326.  
  327. return (SUCCESS);
  328. }
  329.  
  330. /*****************************************************************/
  331.  
  332. void KillTrackInfo (void)
  333.  
  334. {
  335. if (TrackPool != NULL)
  336.   LibDeletePool (TrackPool);
  337. }
  338.